package cn.sc.summer.auth.filter;

import cn.hutool.core.util.StrUtil;
import cn.sc.summer.auth.filter.base.BaseAuthenticationFilter;
import cn.sc.summer.auth.token.SmsCodeLoginToken;
import cn.sc.summer.auth.util.ValidateCodeUtil;
import cn.sc.summer.token.constant.LoginAPIConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * 类名：手机号+短信验证码登录
 *
 * @author a-xin
 * @date 2023/11/28 14:36
 */
@Slf4j
public class SmsCodeLoginFilter extends BaseAuthenticationFilter {

    private static final long serialVersionUID = -7449381592700422377L;

    public SmsCodeLoginFilter() {
        super(new AntPathRequestMatcher(LoginAPIConstant.SMS_LOGIN, DEFAULT_METHOD));
    }

    private static final String USER_TEL = "userTel";
    private static final String PATH = "path";

    /**
     * Request a parameter validation
     *
     * @param requestParam Parameter information of the request
     */
    @Override
    protected void paramCheck(HttpServletRequest request, Map<String, String> requestParam) {
        String userTel = requestParam.getOrDefault(USER_TEL, "");
        String smsCode = requestParam.getOrDefault(ValidateCodeUtil.SMS_CODE, "");
        if (StrUtil.isBlank(userTel) || StrUtil.isBlank(smsCode)) {
            throw new AuthenticationServiceException("The userTel or smsCode can not be null！");
        }
        String smsRandomKey = request.getHeader(ValidateCodeUtil.SMS_RANDOM_KEY);
        if (StrUtil.isBlank(smsRandomKey)) {
            throw new AuthenticationServiceException("The check data cannot be empty！");
        }
    }

    /**
     * The verification is successful, and the login authentication information is encapsulated
     *
     * @param request      Request body information
     * @param response     Response body information
     * @param requestParam Parameter information of the request
     * @return the login authentication information
     */
    @Override
    protected Authentication checkSuccess(HttpServletRequest request, HttpServletResponse response, Map<String, String> requestParam) {
        String smsRandomKey = request.getHeader(ValidateCodeUtil.SMS_RANDOM_KEY);
        String userTel = requestParam.get(USER_TEL);
        requestParam.put(ValidateCodeUtil.SMS_RANDOM_KEY, smsRandomKey);
        requestParam.put(PATH, request.getRequestURI());
        SmsCodeLoginToken token = new SmsCodeLoginToken(userTel, smsRandomKey);
        token.setDetails(authenticationDetailsSource.buildDetails(request));
        token.setRequestParam(requestParam);
        return this.getAuthenticationManager().authenticate(token);
    }

    /**
     * Determine the types of data sources supported by this class
     *
     * @return Supported data source types
     */
    @Override
    public String supports() {
        return DEFAULT_METHOD;
    }
}
